/**
 * \file ssi_link_layer.h
 *
 * \brief declaration file of SSI library to handle the ssi link layer frames
 *
 * \author Santiago Carmona Meco
 *
 * Contact santiago.carmonads@gmail.com
 *
 */

// ****************************************
// 	CHANGE LOG
//                SEP-2011  scarmona  Creating this file
//                2011-2012 scarmona  Development of the library and source code modifications
//                FEB-2013  scarmona  Modifications of type names and variable names
//				  26-4-2013 scarmona  Subtle modifications of code style and type definitions in burst structs
//				  21-6-2013 scarmona  Changes in parameters of builder functions and several names
//
// ****************************************

#include <public/ssi_link_layer.h>




//******************************************************
//ssi_link_layer_get_radio_id();
//******************************************************
void ssi_link_layer_get_radio_id(byte_t * pFrame, byte_t *pRadioId)
{
	uint8_t i = 0;

	while (i < 6)
	{
		pRadioId[i] = pFrame[i];
		i++;
	}

}

//******************************************************
//ssi_link_layer_get_sensor_id();
//******************************************************
word16_t ssi_link_layer_get_sensor_id(byte_t *pFrame)
{
	word16_t sensorId = 0;

	sensorId = pFrame[6];
	sensorId = sensorId << 8;
	sensorId = sensorId + pFrame[7];

	return sensorId;
}

//******************************************************
//ssi_link_layer_get_flags();
//******************************************************
byte_t ssi_link_layer_get_flags(byte_t * pFrame)
{
	return pFrame[8];
}

//******************************************************
//ssi_link_layer_get_reserved();
//******************************************************
void ssi_link_layer_get_reserved(byte_t * pFrame, byte_t *pReserved)
{
	uint8_t i = 0;

	while (i < 6)
	{
		pReserved[i] = pFrame[9 + i];
		i++;
	}

}

//******************************************************
//ssi_link_layer_get_data_length();
//******************************************************
byte_t ssi_link_layer_get_data_length(byte_t * pFrame)
{
	return pFrame[15];
}

//******************************************************
//ssi_link_layer_get_data();
//******************************************************
void ssi_link_layer_get_data(byte_t *pFrame, byte_t *pData)
{
	uint8_t i = 0;

	while (i < 32)
	{
		pData[i] = pFrame[16 + i];
		i++;
	}
}


//******************************************************
//ssi_link_layer_is_ack();
//******************************************************
bool_t ssi_link_layer_is_ack(byte_t * pFrame)
{

	if ((MASK_ACK_SSI & pFrame[8]) == MASK_ACK_SSI)
	{
		return 1;
	}
	else
	{
		return 0;
	}

}

//******************************************************
//ssi_link_layer_is_discovery();
//******************************************************
bool_t ssi_link_layer_is_discovery(byte_t * pFrame)
{
	if ((MASK_DISCOVERY_SSI & pFrame[8]) == MASK_DISCOVERY_SSI)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//******************************************************
//ssi_link_layer_is_space();
//******************************************************
bool_t ssi_link_layer_is_space(byte_t * pFrame)
{
	if ((MASK_SPACE_SSI & pFrame[8]) == MASK_SPACE_SSI)
	{
		return 1;
	}
	else
	{
		return 0;
	}

}

//******************************************************
//ssi_link_layer_is_ground();
//******************************************************
bool_t ssi_link_layer_is_ground(byte_t * pFrame)
{
	if ((MASK_GROUND_SSI & pFrame[8]) == MASK_GROUND_SSI)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//******************************************************
//ssi_link_layer_is_data();
//******************************************************
bool_t ssi_link_layer_is_data(byte_t * pFrame)
{
	if ((MASK_DATA_SSI & pFrame[8]) == MASK_DATA_SSI)
	{
		return 1;
	}
	else
	{
		return 0;
	}

}



//******************************************************
//sensor_id_is_bidirectional();
//******************************************************

//TODO: en los 'requisitos' pone que los sensores se tienen que identificar a traves de una lista, no por identificador
// estaría aun por definir
bool_t ssi_link_layer_sensor_id_is_bidirectional(word16_t sensorId)
{

	if ((MASK_BIDIRECTIONAL_SSI & sensorId) == MASK_BIDIRECTIONAL_SSI)
	{
		return 1;
	}
	else
	{
		return 0;
	}

}



//******************************************************
//get_frame_type();
//******************************************************
FrameTypeReceived_t ssi_link_layer_get_frame_type(byte_t * pFrame)
{
	if (ssi_link_layer_is_ack(pFrame))
	{
		return FrameTypeIsSSIAck;
	}
	else if (ssi_link_layer_is_discovery(pFrame))
	{
		return FrameTypeIsSSIDiscovery;
	}
	else if (ssi_link_layer_is_data(pFrame))
	{
		return FrameTypeIsSSIData;
	}

	return FrameTypeIsSSIDefault;
}


//******************************************************
//ssi_link_layer_check_data_frame_crc();
//******************************************************
bool_t ssi_link_layer_check_data_frame_crc(byte_t * pFrame)
{
	word16_t crcRecibido = 0;

	crcRecibido = pFrame[48];
	crcRecibido = crcRecibido << 8;
	crcRecibido = crcRecibido + pFrame[49];

	return check_CRC_word16(48, pFrame, crcRecibido);

}

//******************************************************
//ssi_link_layer_check_signal_frame_crc();
//******************************************************
bool_t ssi_link_layer_check_signal_frame_crc(byte_t * pFrame)
{
	word16_t crcRecibido = 0;

	crcRecibido = pFrame[15];
	crcRecibido = crcRecibido << 8;
	crcRecibido = crcRecibido + pFrame[16];

	return check_CRC_word16(15, pFrame, crcRecibido);

}


//******************************************************
//ssi_link_layer_add_crc_to_data_frame();
//******************************************************
void ssi_link_layer_add_crc_to_data_frame(byte_t * pframe)
{
	word16_t codigoCRC;

	codigoCRC = calculate_CRC_word16(48, pframe);
	pframe[49] = codigoCRC;
	pframe[48] = codigoCRC >> 8;

}

//******************************************************
//ssi_link_layer_add_crc_to_signal_frame();
//******************************************************
void ssi_link_layer_add_crc_to_signal_frame(byte_t * pframe)
{
	word16_t codigoCRC;

	codigoCRC = calculate_CRC_word16(15, pframe);
	pframe[16] = codigoCRC;
	pframe[15] = codigoCRC >> 8;

}


//******************************************************
//ssi_link_layer_build_data_frame();
//******************************************************
void ssi_link_layer_build_data_frame(byte_t * pFrame, SSI_data_frame_t frameInfo)
{
	//radio_id
	uint8_t i = 0;
	while (i < 6)
	{
		pFrame[i] = frameInfo.radio_id[i];
		i++;
	}
	//sensor_id
	pFrame[6] = frameInfo.sensor_id >> 8;
	pFrame[7] = frameInfo.sensor_id;
	//flags
	pFrame[8] = frameInfo.flags;
	//reserved
	i = 0;
	while (i < 6)
	{
		pFrame[i + 9] = frameInfo.reserved[i];
		i++;
	}
	//length
	pFrame[15] = frameInfo.length;
	//data
	i = 0;
	while (i < 32)
	{
		pFrame[i + 16] = frameInfo.data[i];
		i++;
	}
	ssi_link_layer_add_crc_to_data_frame(pFrame);

}



//******************************************************
//ssi_link_layer_build_signal_frame();
//******************************************************
void ssi_link_layer_build_signal_frame(byte_t * pFrame, SSI_signal_frame_t frameInfo)
{
	//radio_id
	uint8_t i = 0;

	while (i < 6)
	{
		pFrame[i] = frameInfo.radio_id[i];
		i++;
	}
	//sensor_id
	pFrame[6] = frameInfo.sensor_id >> 8;
	pFrame[7] = frameInfo.sensor_id;
	//flags
	pFrame[8] = frameInfo.flags;
	//reserved
	i = 0;
	while (i < 6)
	{
		pFrame[i + 9] = frameInfo.reserved[i];
		i++;
	}

	ssi_link_layer_add_crc_to_signal_frame(pFrame);

}

//******************************************************
//build_ack();
//******************************************************
void ssi_link_layer_build_ack(byte_t *pFrame,byte_t *radioId,word16_t sensorId)

{
	uint8_t i=0;
	SSI_signal_frame_t ackFrame;
	for (i=0;i<6;i++)
	{
		ackFrame.radio_id[i]=radioId[i];
	}
	ackFrame.sensor_id=sensorId;
	ackFrame.flags=MASK_ACK_SSI;//FLAG ACK

	ssi_link_layer_build_signal_frame(pFrame,ackFrame);

}


//******************************************************
//ssi_link_layer_get_data_frame_info();
//******************************************************
void ssi_link_layer_get_data_frame_info(byte_t * pFrame, SSI_data_frame_t *pFrameInfo)
{
	ssi_link_layer_get_radio_id(pFrame, pFrameInfo->radio_id);
	pFrameInfo->sensor_id = ssi_link_layer_get_sensor_id(pFrame);
	pFrameInfo->flags = ssi_link_layer_get_flags(pFrame);
	ssi_link_layer_get_reserved(pFrame, pFrameInfo->reserved);
	pFrameInfo->length = ssi_link_layer_get_data_length(pFrame);
	ssi_link_layer_get_data(pFrame, pFrameInfo->data);
}

//******************************************************
//ssi_link_layer_get_signal_frame_info();
//******************************************************
void ssi_link_layer_get_signal_frame_info(byte_t * pFrame, SSI_signal_frame_t *pFrameInfo)
{
	ssi_link_layer_get_radio_id(pFrame, pFrameInfo->radio_id);
	pFrameInfo->sensor_id = ssi_link_layer_get_sensor_id(pFrame);
	pFrameInfo->flags = ssi_link_layer_get_flags(pFrame);
	ssi_link_layer_get_reserved(pFrame, pFrameInfo->reserved);


}

